/*
 * ounit - an OPAQUE compliant framework for Computer Aided Testing
 *
 * Copyright (C) 2010  Antti Andreimann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package com.googlecode.ounit.maven;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.maven.plugin.MojoExecutionException;

/**
 * Generate required settings at the start of a student project build
 * 
 * Currently it generates a policy used to sandbox unit tests and cleans up
 * report directories. Additional file generation tasks that require taking the
 * current Maven or project settings into account may be implemented in the
 * future.
 * 
 * @goal setup-student
 * @phase generate-sources
 */

public class SetupStudentMojo extends MojoData {
	/**
	 * Location where files are
	 * 
	 * @parameter expression="${basedir}"
	 */
	protected File baseDirectory;

	public void execute() throws MojoExecutionException {
		cleanReportDirectories();
		generateTestPolicy();
	}
	
	public void cleanReportDirectories() {
		List <File> testDirs = getTeacherTestDirectories();
		testDirs.add(new File(getOunitDirectory()));
		testDirs.addAll(getStudentTestDirectories());
		for(File dir: testDirs) {
			deleteDirectory(dir);
		}
	}
	
	public void generateTestPolicy() throws MojoExecutionException {
		try {
			/*
			 * Create a policy file
			 * 
			 * We have to use properties from the current build, but
			 * unfortunately they can not be properly passed to java command
			 * line so the only viable solution is to use a separate mojo
			 * that generates this file and attach it to a correct phase.
			 */

			String marker = "/* The lines below were automatically generated by ounit DO NOT EDIT */";
			File polFile = new File(baseDirectory, "tests.policy");
			List <String> policyLines = new ArrayList<String>();
			try {
				FileReader in = new FileReader(polFile);
				BufferedReader r = new BufferedReader(in);
				String l;
				while((l = r.readLine()) != null) {
					// Stop reading after we hit the marker
					if(l.startsWith(marker))
						break;
					policyLines.add(l);
				}
				in.close();
			} catch(FileNotFoundException e) {
				// Ignore error if file does not exist
			}

			// Allow code in Maven repository and target/bin to do anything
			policyLines.add(marker);
			
			// Create ugly "policy file friendly" URL-s.
			// We can't simply use @ArtifactRepository#getUrl() because Java
			// policy manager is too dumb to unescape %20-s
			policyLines.add("grant codeBase \"file:" +
					session.getLocalRepository().getBasedir() +
					  "/-\" { permission java.security.AllPermission; };");
			policyLines.add("grant codeBase \"file:${user.dir}/bin/-\"" +
					  " { permission java.security.AllPermission; };");

			FileWriter out = new FileWriter(polFile);
			for(String l: policyLines)
				out.write(l + "\n");
			out.close();		
		} catch (IOException e) {
			throw new MojoExecutionException("Failed to generate test policy", e);
		}
	}

    /**
     * Helper function to recursively delete a directory.
     * 
     * @param path
     * @return
     */
    public static boolean deleteDirectory(File path) {
            if (path.exists()) {
                    File[] files = path.listFiles();
                    for (int i = 0; i < files.length; i++) {
                            if (files[i].isDirectory()) {
                                    deleteDirectory(files[i]);
                            } else {
                                    files[i].delete();
                            }
                    }
            }
            return (path.delete());
    }
}